@h2loop/uav 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -59,7 +59,9 @@ skills/uav/ # on-demand `uav` skill + references
59
59
  data/ # bundled apm-params.json + built-in defaults
60
60
  bridge/ # optional MAVLink→MCP Python bridge
61
61
  plugins/ # BUILT bundle (index.js + worker/) — generated
62
- mcp.json # exa + mavlink MCP servers (disabled by default)
62
+ mcp.json # exa MCP server (disabled by default); mavlink is registered
63
+ # from src/index.ts's config hook — it needs a resolved
64
+ # interpreter + an ABSOLUTE script path, which static JSON can't give
63
65
  ```
64
66
 
65
67
  ## Run standalone
@@ -235,30 +237,29 @@ project KG.
235
237
 
236
238
  A local Python stdio server. Read-only tools: `read_params`, `param_get`, `param_get_all`,
237
239
  `get_messages`, `tail_telemetry`, `get_flight_mode`, `get_status`. The write tier
238
- (`param_set` / `param_set_batch`) is **off by default** — see below.
240
+ (`param_set` / `param_set_batch`) is **on by default** so tune→push→retest works out of the
241
+ box — see below.
239
242
 
240
243
  **Requires:**
241
- - Python ≥ 3.10 with `pymavlink>=2.4.49` and `mcp[cli]>=1.0.0` installed. The pack does **not**
244
+ - Python ≥ 3.10 with `pymavlink>=2.4.49` and `mcp[cli]>=1.0.0,<2` installed. The pack does **not**
242
245
  auto-provision a venv — install the deps yourself: `pip install -r bridge/requirements.txt`
243
246
  (ideally into a venv), and point the command's `python3` at that interpreter.
244
247
  - A reachable MAVLink endpoint (e.g. `udp:127.0.0.1:14550` from SITL or a telemetry radio),
245
248
  or a `.tlog`/`.log` file for offline replay.
246
249
  - The `bridge/` directory ships with the plugin (the `mcp.json` references it).
247
250
 
248
- Enable per-project in your Hydron config. **Param writes are OFF by default** (the bridge
249
- defaults to `--read-only`). To enable the tune→push→retest write tier, the command must pass
250
- **both** `--no-read-only` **and** `--allow-param-write`. ⚠ this lets the agent write params to
251
- a **live vehicle** — prefer SITL/bench.
252
- ```jsonc
253
- "mcp": {
254
- "mavlink": {
255
- "enabled": true,
256
- "command": ["python3", "<plugin-path>/bridge/uav_mavlink_bridge.py",
257
- "--connect", "udp:127.0.0.1:14550",
258
- "--no-read-only", "--allow-param-write"]
259
- }
260
- }
251
+ Ships **enabled**, with param writes **on** — the command passes `--no-read-only`
252
+ `--allow-param-write`, so `param_set` / `param_set_batch` are registered and the tuning loop
253
+ works with no configuration. ⚠ this lets the agent write params to a **live vehicle** — prefer
254
+ SITL/bench. To ship read-only, drop both flags.
255
+
256
+ No `--connect` is passed, so the target comes from the **`MAVLINK_CONNECT`** env var, falling
257
+ back to `udp:127.0.0.1:14550`:
258
+ ```bash
259
+ export MAVLINK_CONNECT=serial:/dev/ttyUSB0:57600 # COM3:57600 on Windows
261
260
  ```
261
+ Don't put it in the server's `environment` block — Hydron spreads that *over* `process.env`, so
262
+ it would shadow your export instead of defaulting to it.
262
263
 
263
264
  Connect-target forms: `udp:HOST:PORT` (default `udp:127.0.0.1:14550` = SITL/MAVProxy) |
264
265
  `tcp:HOST:PORT` | `serial:/dev/ttyUSB0:BAUD` | `/path/log.tlog` (offline replay); can also be
package/USAGE.md CHANGED
@@ -12,7 +12,7 @@ covers getting it running on **macOS, Linux, and Windows**, validating it works,
12
12
  - **Bun** — *only* needed to build the bundle from source or run the pack's tests; **not**
13
13
  needed to use a published pack.
14
14
  - **Python ≥ 3.10** — *only* for the optional live MAVLink bridge (`pymavlink>=2.4.49` +
15
- `mcp[cli]>=1.0.0`). The pack does **not** auto-provision a venv; you install the deps
15
+ `mcp[cli]>=1.0.0,<2`). The pack does **not** auto-provision a venv; you install the deps
16
16
  yourself (see §6). Plain `.bin` log analysis needs no Python.
17
17
  - *Optional:* `export EXA_API_KEY=…` for web grounding of bounds.
18
18
  - **macOS, Linux, and Windows are all native** — no WSL required. The pack resolves the Python
@@ -127,50 +127,67 @@ See `skills/uav/references/project-config.md` for the full list (`uav-thresholds
127
127
  A **MAVLink→MCP bridge**: a local Python stdio server Hydron spawns so the agent can query a
128
128
  live vehicle / SITL / log replay. Read-only tools: `get_status`, `get_flight_mode`,
129
129
  `read_params`, `param_get`, `param_get_all`, `get_messages`, `tail_telemetry`. The **write**
130
- tools `param_set`/`param_set_batch` are **off by default** (see the ⚠ note below).
130
+ tools `param_set`/`param_set_batch` are **on by default**, so tune→push→retest works out of
131
+ the box (see the ⚠ note below to turn them off).
131
132
 
132
- ### Install the Python deps yourself
133
+ ### Install the Python deps (the only manual step)
133
134
  The pack does **not** auto-provision a venv. The bridge needs Python ≥ 3.10 with
134
- `pymavlink>=2.4.49` and `mcp[cli]>=1.0.0`:
135
+ `pymavlink>=2.4.49` and `mcp[cli]>=1.0.0,<2`:
135
136
  ```bash
136
137
  pip install -r bridge/requirements.txt # ideally into a venv
137
138
  ```
138
- Then point the `mavlink` command's first element at that interpreter. **This is the one place
139
- the interpreter is not auto-detected** — `mcp.json` is static config that Hydron spawns
140
- directly, so it ships the POSIX default `python3`. On Windows change it to `python` (or the
141
- venv's full `…\Scripts\python.exe`); everywhere else an absolute venv path is the safest value.
142
-
143
- ### Enable and configure (per-project in opencode.jsonc)
144
- The `mavlink` server ships in `mcp.json` **disabled by default**. Enable it per-project:
145
- ```jsonc
146
- "mcp": {
147
- "mavlink": {
148
- "enabled": true,
149
- "command": ["python3", "<plugin-path>/bridge/uav_mavlink_bridge.py",
150
- "--connect", "udp:127.0.0.1:14550"]
151
- }
152
- }
139
+ > The `<2` bound is required, not cosmetic: the MCP Python SDK **removed `mcp.server.fastmcp`
140
+ > in 2.x**, so the bridge fails at import on `mcp>=2`. Verified working on 1.29.0.
141
+
142
+ You do **not** need to edit any command. The plugin registers the `mavlink` server itself at
143
+ startup, resolving:
144
+
145
+ - **the interpreter** — via the same probe-by-execution resolver the `.tlog`/`.ulog` decoders
146
+ use, so `python3` / `python` / the Windows `py -3` launcher are all handled and Windows'
147
+ Microsoft-Store alias stubs are rejected. Pin a specific one with `UAV_PYTHON` (e.g. a venv:
148
+ `export UAV_PYTHON=/path/.venv/bin/python`, or `…\Scripts\python.exe` on Windows).
149
+ - **the script path** — absolute, inside the installed plugin bundle. This matters: Hydron
150
+ spawns local MCP servers with the cwd set to *your project*, so a bundle-relative path can
151
+ never resolve. That is why the server is no longer declared in `mcp.json`.
152
+
153
+ If no usable Python is found the server is not registered at all; if Python is found but can't
154
+ `import mcp, pymavlink`, it is registered **disabled** — so you see it listed rather than
155
+ getting a failed server on every launch. Check with `hydron mcp list`.
156
+
157
+ ### Point it at your vehicle
158
+ The `mavlink` server is registered **enabled**, with param writes on, so nothing needs enabling.
159
+ The one thing you may need to change is the connect target.
160
+
161
+ The command passes **no** `--connect`, so the bridge falls back to its own default —
162
+ which reads the **`MAVLINK_CONNECT`** environment variable, then `udp:127.0.0.1:14550`. So for
163
+ anything other than local SITL/MAVProxy, just export the target:
164
+ ```bash
165
+ export MAVLINK_CONNECT=serial:/dev/ttyUSB0:57600 # or COM3:57600 on Windows
153
166
  ```
154
167
  Connect-target forms: `udp:HOST:PORT` (default `udp:127.0.0.1:14550` = SITL/MAVProxy) |
155
168
  `tcp:HOST:PORT` | `serial:/dev/ttyUSB0:BAUD` (on Windows a COM port, e.g. `COM3` or
156
- `COM3:57600`) | `/path/log.tlog` (offline replay). Can also be set via the `MAVLINK_CONNECT`
157
- env on the server.
169
+ `COM3:57600`) | `/path/log.tlog` (offline replay).
170
+
171
+ > Set it in the environment, **not** in the server's `environment` block: Hydron spawns local
172
+ > MCP servers with `{...process.env, ...environment}`, so a server-level entry *shadows* your
173
+ > export rather than acting as a default. That is why the plugin sets neither.
158
174
 
159
175
  > **"Connected" ≠ a live vehicle.** The panel shows `mavlink Connected` once the bridge *process*
160
176
  > starts. The tools only return data while something is **actually publishing MAVLink** at the
161
177
  > connect target. With no source, calls return empty / time out (`-32001`). Start your SITL/vehicle
162
178
  > (or leave it — log analysis via `uav_analyze` doesn't need the live bridge).
163
179
 
164
- > **Param writes are OFF by default.** The bridge defaults to `--read-only`. To enable the
165
- > tune→push→retest write tier (`param_set` / `param_set_batch`), the command must pass **both**
166
- > `--no-read-only` **and** `--allow-param-write`:
167
- > ```jsonc
168
- > "command": ["python3", "<plugin-path>/bridge/uav_mavlink_bridge.py",
169
- > "--connect", "udp:127.0.0.1:14550",
170
- > "--no-read-only", "--allow-param-write"]
180
+ > **⚠ Param writes are ON by default.** The shipped command passes `--no-read-only`
181
+ > `--allow-param-write`, which registers the tune→push→retest write tier (`param_set` /
182
+ > `param_set_batch`). This lets the agent **write parameters to a live vehicle**. Prefer
183
+ > SITL/bench, and point `MAVLINK_CONNECT` at a real airframe only when you intend that.
184
+ >
185
+ > To ship read-only, remove both flags from the `config` hook in `src/index.ts` — the bridge's own defaults are
186
+ > `read_only=True` / `allow_param_write=False`, and the write tools are then never registered:
187
+ > ```ts
188
+ > command: [...py, script], // no --no-read-only / --allow-param-write
171
189
  > ```
172
- > ⚠ this lets the agent **write parameters to a live vehicle** — prefer SITL/bench, and point
173
- > `--connect` at a real airframe only when you intend that.
190
+ > Reads (`param_get`, `param_get_all`, `read_params`, telemetry) are unaffected either way.
174
191
 
175
192
  ---
176
193
 
@@ -1,2 +1,6 @@
1
1
  pymavlink>=2.4.49
2
- mcp[cli]>=1.0.0
2
+ # Pinned below 2.0: the MCP Python SDK removed `mcp.server.fastmcp` in 2.x (FastMCP is gone,
3
+ # replaced by a different MCPServer API), so this bridge fails at import on mcp>=2. The
4
+ # unpinned `>=1.0.0` silently floated into that breaking major. Porting to the 2.x server API
5
+ # is a separate change; until then this range is the supported one (verified on 1.29.0).
6
+ mcp[cli]>=1.0.0,<2
package/mcp.json CHANGED
@@ -4,12 +4,6 @@
4
4
  "url": "https://mcp.exa.ai/mcp",
5
5
  "headers": { "x-api-key": "${EXA_API_KEY}" },
6
6
  "enabled": false
7
- },
8
- "mavlink": {
9
- "type": "local",
10
- "enabled": false,
11
- "command": ["python3", "./bridge/uav_mavlink_bridge.py", "--connect", "udp:127.0.0.1:14550"],
12
- "environment": { "MAVLINK_DIALECT": "ardupilotmega" },
13
- "timeout": 10000
14
7
  }
15
8
  }
9
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h2loop/uav",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "UAV domain pack for Hydron — ArduPilot/PX4 flight-log intelligence (analyze, triage, compare, tune)",
5
5
  "type": "module",
6
6
  "private": false,